﻿using System;
using HAVNet.Intros.AST;

namespace HAVNet.CoreTesting
{
    // ASTNamespaceMemberDecl
    //     ASTNamespaceNamespace           namespace Alejandro.Varela      
    //     ASTNamespaceTypeDecl                     
    //         ASTTypeDeclClass            class       CoolParser      { ...
    //         ASTTypeDeclStruct           struct      SimpleToken     { ...
    //         ASTTypeDeclInterface        interface   IProgrammer     { ...
    //         ASTTypeDeclEnum             enum        Paradigms       { Procedural, Functional, OOP, Logic, } [;]
    //         ASTTypeDeclDelegate         delegate    Func<int,int> myCurry (int x) [;]

    public delegate void NamespaceMemberDeclFound (ASTNamespaceMemberDecl nmd, int depth);
    
    public class WalkerNamespaceMemberDecls
    {
        public static void get (ASTNamespaceMemberDecls nmds, NamespaceMemberDeclFound f, int depth )
        {
            nmdsTraverse (nmds, f, depth);
        }

        static void nmdsTraverse (ASTNamespaceMemberDecls nmds, NamespaceMemberDeclFound f, int depth)
        {
            foreach (ASTNamespaceMemberDecl nmd in nmds)
            {
                f (nmd, depth);

                if (nmd is ASTNamespaceNamespace)
                    nmdsTraverse(nmd.namespaceMemberDecls, f, depth + 1);
                else if (nmd is ASTTypeDeclClass)
                    typeMembersTraverse(((ASTTypeDeclClass)nmd).members, f, depth + 1);
                else if (nmd is ASTTypeDeclStruct)
                    typeMembersTraverse(((ASTTypeDeclStruct)nmd).members, f, depth + 1);
            }
        }

        static void typeMembersTraverse (ASTMemberDecls memberDecls, NamespaceMemberDeclFound f, int depth)
        {
            foreach (ASTMemberDecl member in memberDecls)
            {
                if (member is ASTMemberDeclTypeDecl)
                {
                    ASTMemberDeclTypeDecl memberTypeDecl = (ASTMemberDeclTypeDecl)member;

                    f (memberTypeDecl.typeDecl, depth);

                    if (memberTypeDecl.typeDecl is ASTTypeDeclClass)
                        typeMembersTraverse(((ASTTypeDeclClass)memberTypeDecl.typeDecl).members, f, depth + 1);
                    else if (memberTypeDecl.typeDecl is ASTTypeDeclStruct)
                        typeMembersTraverse(((ASTTypeDeclStruct)memberTypeDecl.typeDecl).members, f, depth + 1);
                }
            }
        }
    }
}
